/*==========================================================================*\
 |  $Id: Variable.java 9 2009-11-06 02:47:13Z VTWoods $
 |*-------------------------------------------------------------------------*|
 |  Copyright (C) 2009 Virginia Tech
 |
 |  This file is part of CloudSpace.
 |
 |  CloudSpace is free software; you can redistribute it and/or modify
 |  it under the terms of the GNU General Public License as published
 |  by the Free Software Foundation; either version 3 of the License, or
 |  (at your option) any later version.
 |
 |  CloudSpace is distributed in the hope that it will be useful,
 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 |  GNU General Public License for more details.
 |
 |  You should have received a copy of the GNU General Public License
 |  along with CloudSpace; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/

package student.web;

import org.zkoss.zk.ui.Executions;

import student.web.internal.JavaStatementElement;

//-------------------------------------------------------------------------
/**
 * A ZUL variable declaration.
 * <p>A &lt;variable&gt; tag has two required properties and one optional
 * property:
 * </p>
 * <dl>
 * <dt><b>Parameters</b></dt>
 * <dd><code>type</code> - The (optional) Java type of the variable--this
 *   should be a legal Java class name that is in scope (see
 *   {@link Import}) (<b>must</b> come before the value!).</dd>
 * <dd><code>name</code> - The variable name (<b>must</b> come before the
 *   value!)</dd>
 * <dd><code>value</code> - The variable's value.  It can be any Java
 *   expression, or any EL expression (i.e., ${...}), but may not be a
 *   bound data value (no @{...}).</dd>
 * </dl>
 * <p>Examples:</p>
 * <pre>
 * &lt;variable name="x" value="new Person()"/&gt;
 *
 * &lt;!-- With an included type --&gt;
 * &lt;variable type="Person" name="x" value="new Person()"/&gt;
 *
 * &lt;!-- If you use quotes, they must be HTML-escaped --&gt;
 * &lt;variable name="file"
 *   value="student.IOHelper.getFile(&amp;quot;infile.txt&amp;quot;)"/&gt;
 *
 * &lt;!-- A longer version, so you don't have to escape the quotes. --&gt;
 * &lt;variable name="file2"&gt;
 *   &lt;attribute name="value"&gt;
 *     student.IOHelper.getFile("infile.txt")
 *   &lt;/attribute&gt;
 * &lt;/variable&gt;
 * </pre>
 *
 * @author Stephen Edwards
 * @author Last changed by $Author: VTWoods $
 * @version $Revision: 9 $, $Date: 2009-11-06 02:47:13 +0000 (Fri, 06 Nov 2009) $
 */
public class Variable
    extends JavaStatementElement
{
    //~ Constructor ...........................................................

    // ----------------------------------------------------------
    /**
     * Creates a new Variable component.
     */
    public Variable()
    {
        super();
    }


    //~ Public methods ........................................................

    // ----------------------------------------------------------
    /**
     * Accessor for the "name" property.
     * @return The variable's name
     */
    public String getName()
    {
        return name;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "name" property.  Note that the variable name must
     * be set before the value (which means the name attribute must appear
     * to the left of the value attribute in your ZHTML code).
     * @param newName The name to use for the variable
     */
    public void setName(String newName)
    {
        name = newName;
        setVisible(false);
    }


    // ----------------------------------------------------------
    /**
     * Accessor for the "type" property, which may be null if no type
     * has been specified.
     * @return The variable's type (a Java {@link Class} name)
     */
    public String getType()
    {
        return name;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "type" property, which is optional.  Note that the
     * variable type, if used, must be set before the value (which means the
     * type attribute must appear to the left of the value attribute in your
     * ZHTML code).
     * @param newType The type (class) to use for the variable.  The class
     * name specified must either be fully qualified, or must have been
     * imported (see {@link Import}).
     */
    public void setType(String newType)
    {
        type = newType;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "value" property, which provides the variable's initial
     * value.  It must come after the name and (optional) type.
     * @param newValue The value to use for the variable.  It must either
     * be an object of the appropriate type, or a string that can be
     * interpreted as a Java expression of the appropriate type.
     */
    public void setValue(String newValue)
    {
        setVisible(false);
        value = newValue;
        if (name == null)
        {
            throw new RuntimeException("a variable tag is missing its "
                + "name attribute (or has the value attribute before the "
                + "name attribute; put the value attribute last)");
        }
        String str = (String)value;
        try
        {
            if (str.indexOf("${") >= 0)
            {
                value = Executions.evaluate(this, str, Object.class);
                getParent().setVariable( name, value, false );
            }
            else
            {
                getPage().getInterpreter( getPage().getZScriptLanguage() )
                    .interpret(
                        (type == null ? "" : (type + " "))
                        +
                        getName() + " = " + str + ";",
                        getParent().getNamespace() );
            }
        }
        catch(Exception e)
        {
            student.web.internal.Exceptions.addSimpleExceptionGrid(
                getParent(), e, "In &lt;variable&gt; tag" +
                (getName() == null
                    ? ""
                    : " for \"" + getName() + "\""));
        }
    }


    //~ Instance/static variables .............................................

    private String type;
    private String name;
    private Object value;
}
